/*
 * ColeccionFlotas.h
 *
 *  Created on: 12/01/2010
 *      Author: San Martín, Matías I.
 */

#ifndef COLECCIONFLOTAS_H_
#define COLECCIONFLOTAS_H_

#include <vector>

#include "../../../Middleware/Common/IdFlota.h"
#include "../../../Middleware/Common/IdJugador.h"
#include "../Common/Flota.h"
#include "ParIdJugadorCantidad.h"

using namespace aplicacion;

namespace aplicacion {
namespace planeta {

typedef std::vector<Flota*> t_flotasCollection;

typedef std::pair<IdFlota,size_t> t_parIdFlotaCantidad;

typedef ParIdJugadorCantidad t_parIdJugadorCantidad;

//contiene parejas idFlota, cantidad de naves que arribaron
typedef std::list<t_parIdFlotaCantidad> t_idFlotasCantidadCollection;

/**
 * Representa una colección de flotas
 */
class ColeccionFlotas {

//------------------------------ CONSTANTES ------------------------------
public:

//------------------------------ ATRIBUTOS ------------------------------
private:

	t_flotasCollection _flotas;

	/** mantiene el listado de la cantidad de naves _restantes_ para las flotas
	 * que arribaron alguna nave */
	t_idFlotasCantidadCollection _flotasArribaron;

//------------------------------ METODOS ------------------------------
public:
	ColeccionFlotas();
	virtual ~ColeccionFlotas();

	/** La coleccion se encarga de destruir la flota una vez agregada*/
	void add(Flota* flota);

	/** Permite eliminar todas las flotas cuyo dueño es el indicado
	 *
	 * @return cantidad de flotas eliminadas
	 */
	size_t removeByDuenio(const IdJugador& idDuenio);

	/**
	 * true si tiene asociada una flota con el id indicado
	 */
	bool contains(const IdFlota& idFlota) const;

	/**
	 * Permite obtener el listado de las flotas que arribaron
	 * (puede estar vacia la lista)
	 */
	const t_idFlotasCantidadCollection* getCantidadNavesFlotasArribaron() const;

	/**
	 * Permite obtener el listado de las flotas que arribaron
	 * (puede estar vacia la lista)
	 */
	t_idFlotasCantidadCollection* getCantidadNavesFlotasArribaron();

	/**
	 * devuelve la posición de la flota con id indicado
	 * -1 si no esta la flota
	 */
	ssize_t getIndex(const IdFlota& idFlota) const;

	const Flota& at(size_t index) const;

	Flota& at(size_t index);

	void erase(size_t index);

	size_t size() const;

	/**
	 * Permite establecer el tiempo en el indicado
	 *
	 * @tiempo tiempo a asignar
	 *
	 * @return cantidad de naves de las flotas que arribaron a destino
	 */
	size_t setTiempo(T_TIEMPO tiempo);

	/**
	 * Permite obtener la cantidad de naves que arribaran hasta el tiempo
	 * indicado
	 *
	 * @tiempo hastaTiempo a limite para contar los arribos
	 *
	 * @return cantidad de naves de todas las flota que arribaran a destino para
	 * 			el tiempo indicado
	 *
	 * (este método devuelve el mismo numero que una llamada a setTiempo
	 * pero, a diferencia de este, no remueve las naves de la flota)
	 */
	size_t getCantidadArribaran(T_TIEMPO hastaTiempo) const;

	/**
	 * Hace que arriben las naves de <b>todas</b> las flotas hasta el tiempo
	 * indicado y devuelve el jugador correspondiente a la última nave
	 * que quedo en el supuesto destino (si dos naves llegan al mismo tiempo,
	 * se devuelve uno cualquiera de los jugadores correspondientes).
	 *
	 * @param hastaTiempo tiempo hasta que se desea arribar
	 * @param jugadorInicial jugador y cantidad de naves que se cuentan como
	 * 						base en los arribos. Las naves del mismo jugador
	 * 						se suman a la cuenta y las de los demas se restan.
	 * 						Si las naves de los demas jugadores superan la
	 * 						del jugadorInicial, el resultado contendra el jugador
	 * 						que arribo mayor cantidad de naves.
	 * @return par que indica el jugador que le quedo la mayor cantidad de
	 * 			naves y la cantidad de naves que le quedaron. Puede
	 * 			ser el jugadorInicial teniendo en cuenta la cantidad
	 * 			inicial indicada
	 */
	ParIdJugadorCantidad getQuedoUltimo(T_TIEMPO hastaTiempo,
										const ParIdJugadorCantidad& jugadorInicial);

	/**
	 * Permite obtener el tiempo en que arribaran las próximas "cantidadNaves"
	 * de la colección (pertenecientes a <b>cualquiera</b> de las flotas)
	 *
	 * @return tiempo en que arribaran las proximas "cantidadNaves" (NO el
	 * 			momento) o
	 * 			TIEMPO_MAX si no existe esa cantidad de naves para arribar
	 */
	T_TIEMPO getTiempoArribaran(size_t cantidadNaves) const;

private:

	/**
	 * permite agregar o actualizar la informacion en _flotasArribaron de la
	 * flota indicada que arribo naves
	 */
	void addFlotaArriboNaves(const Flota& flota);

};

#endif /* COLECCIONFLOTAS_H_ */

} //namespace planeta
} //namespace aplicacion
